using System;

namespace Fadd.Globalization
{
	#region DurationDetail enumeration

	/// <summary>
	/// Enumeration specifying a detail level in which to display a duration
	/// </summary>
	public enum DurationDetail
	{
		/// <summary>
		/// Display duration in months and years
		/// </summary>
		Months = 5,

		/// <summary>
		/// Display duration in days, months and years
		/// </summary>
		Days = 4,

		/// <summary>
		/// Display duration in hours, days, months and years
		/// </summary>
		Hours = 3,

		/// <summary>
		/// Display duration in hours, days, months and years
		/// </summary>
		Minutes = 2,

		/// <summary>
		/// Display duration down to the second
		/// </summary>
		Seconds = 1
	}

	#endregion

    /// <summary>
    /// Interface for all localized date/time helpers.
    /// </summary>
    public interface IDateTimeHelper
    {
        /// <summary>
        /// Will try to parse the date/time using the local parser.
        /// Will also try the default DateTime.Parse method if date is in an unknown format.
        /// </summary>
        /// <param name="value">date/time string</param>
        /// <returns>A <see cref="DateTime"/></returns>
        /// <exception cref="FormatException">If the date/time format is invalid.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If month/day/hour/minute/second are not within their ranges.</exception>
        DateTime ParseDateTime(string value);

        /// <summary>
        /// Will try to parse the date/time using the local parser.
        /// Will also try the default DateTime.Parse method if date is in an unknown format.
        /// </summary>
        /// <param name="date">date string (may be null/empty).</param>
        /// <param name="time">time string (may be null/empty).</param>
        /// <returns>A <see cref="DateTime"/></returns>
        /// <exception cref="FormatException">If the date/time format is invalid.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If month/day/hour/minute/second are not within their ranges.</exception>
        DateTime ParseDateTime(string date, string time);

        /// <summary>
        /// Tries to parse a date string.
        /// </summary>
        /// <param name="value">Can contain a complete date or parts of it (which parts depends on the country).</param>
        /// <returns>A <see cref="DateTime"/></returns>
        /// <exception cref="FormatException">If the date format is invalid.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If month/day are not within their ranges.</exception>
        DateTime ParseDate(string value);

        /// <summary>
        /// Tries to parse a date string.
        /// </summary>
        /// <param name="value">Can contain a complete date or parts of it (which parts depends on the country).</param>
        /// <param name="values">array that parsed values are written to.</param>
        /// <param name="offset">where in array to start write values</param>
        /// <exception cref="FormatException">If the date format is invalid.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If month/day are not within their ranges.</exception>
        void ParseDate(string value, int[] values, int offset);


        /// <summary>
        /// Tries to parse a time string.
        /// </summary>
        /// <param name="value">Can contain a complete time or parts of it (which parts depends on the country).</param>
        /// <returns>A <see cref="DateTime"/></returns>
        /// <exception cref="FormatException">If the time format is invalid.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If hour/minute/second are not within their ranges.</exception>
        DateTime ParseTime(string value);


        /// <summary>
        /// Tries to parse a time string.
        /// </summary>
        /// <param name="value">Can contain a complete time or parts of it (which parts depends on the country).</param>
        /// <param name="values">array that will be filled. Must contain three slots.</param>
        /// <param name="offset">Where in the array to start write values</param>
        /// <exception cref="FormatException">If the time format is invalid.</exception>
        /// <exception cref="ArgumentOutOfRangeException">If hour/minute/second are not within their ranges.</exception>
        void ParseTime(string value, int[] values, int offset);

        /// <summary>
        /// Validate a date.
        /// </summary>
        /// <param name="year">year value</param>
        /// <param name="month">month value</param>
        /// <param name="day">day value</param>
        /// <param name="throwException">true if exceptions should be thrown on incorrect values.</param>
        /// <returns>true if specified values are a correct date; otherwise false.</returns>
        bool ValidateDate(int year, int month, int day, bool throwException);

        /// <summary>
        /// Validate 
        /// </summary>
        /// <param name="hour">hour</param>
        /// <param name="minute">minute</param>
        /// <param name="second">second</param>
        /// <param name="throwException">true if exceptions should be thrown on incorrect values.</param>
        /// <returns>true if specified values are a correct date; otherwise false.</returns>
        bool ValidateTime(int hour, int minute, int second, bool throwException);

        /// <summary>
        /// Format a date as a string.
        /// </summary>
        /// <param name="dateTime">A date/time</param>
        /// <returns>Examples: "Yesterday", "On monday"</returns>
        string FormatDate(DateTime dateTime);

        /// <summary>
        /// Format a date/time as a string.
        /// </summary>
        /// <param name="dateTime">A date/time</param>
        /// <returns>Examples: "Yesterday at 12:20pm", "On monday at 11:38am"</returns>
        string FormatDateTime(DateTime dateTime);

    	/// <summary>
    	/// Get duration as a human friendly string.
    	/// </summary>
    	/// <param name="from">Start time of duration</param>
    	/// <param name="to">End time of duration</param>
    	/// <param name="durationDetail">The detail in which to display the duration</param>
    	/// <param name="measures">Number of time units to display</param>
    	/// <returns>
    	/// A string like: 1 month, 2 weeks, and 3 days.
    	/// </returns>
    	string GetDuration(DateTime from, DateTime to, DurationDetail durationDetail, int measures);

        /// <summary>
        /// Get duration as a human friendly string. Displays all time unit durations.
        /// </summary>
        /// <param name="from">Start time of duration</param>
        /// <param name="to">End time of duration</param>
        string GetDuration(DateTime from, DateTime to);

		/// <summary>
		/// Get duration as a human friendly string.
		/// </summary>
		/// <param name="span">The timespan for which to output the duration</param>
		/// <param name="durationDetail">The detail in which to display the duration</param>
        /// /// <param name="measures">Number of time measures to display</param>
		/// <returns>
		/// A string like: 1 month, 2 weeks, and 3 days.
		/// </returns>
		/// <remarks><see cref="DurationDetail.Months"/> cannot be used when using this method since counting of months
		/// requires both to and from datetime information, in such a case user <see cref="GetDuration(DateTime,DateTime,DurationDetail,int)"/></remarks>
		string GetDuration(TimeSpan span, DurationDetail durationDetail, int measures);

        /// <summary>
        /// Get duration as a human friendly string. Displays all time unit durations.
        /// </summary>
        /// <param name="span">The timespan for which to output the duration</param>
        string GetDuration(TimeSpan span);
    }

}
